#include <sel4/types.h>
#include <dite/dite.h>
#include <string.h>

#ifndef BIT
    #define BIT(n) (1<<(n))
#endif
#ifndef MASK
    #define MASK(n) (BIT(n) - 1)
#endif

extern unsigned char _start[1];

/* Locate and return the address of the DITE header. */
struct Dite_Dhdr *
dite_gethdr(void)
{
    void *addr;

    /* The header exists in the section preceding .text at a page-aligned
     * address and begins with the string "dhdr". The section is <= a page and,
     * if you've correctly used a linker script to position the entry point
     * (_start) at the beginning of .text, this loop should find the header in
     * the first iteration.
     */
    for (addr = (void*)(((seL4_Word)_start - BIT(seL4_PageBits)) & ~MASK(seL4_PageBits));
         addr > 0; addr -= BIT(seL4_PageBits)) {
        if (!strncmp(addr, "dhdr", 4)) {
            return (struct Dite_Dhdr*)addr;
        }
    }
    /* We didn't find the header. */
    return NULL;
}

struct Dite_Phdr *
dite_getentry(struct Dite_Dhdr *dite_hdr, int pos)
{
    return (struct Dite_Phdr*) (((char*)dite_hdr + dite_hdr->d_phoff) +
            (pos * dite_hdr->d_phsize));
}

struct Dite_Phdr *
dite_lookup(struct Dite_Dhdr *dite_hdr, char *name)
{
    struct Dite_Phdr *phdr;
    int i;

    for (i=0; i < dite_hdr->d_phnum; i++) {
        phdr = dite_getentry(dite_hdr, i);
        if (strcmp(phdr->p_name, name) == 0) {
            return phdr;
        }
    }

    return NULL;
}
